package com.ti.demo.autoconfigure.log;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import org.slf4j.MDC;
import org.zalando.logbook.*;

import java.io.IOException;
import java.time.ZoneId;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @description: StructuredHttpLogFormatter接口实现类，用于格式化biz日志
 * @Author Triagen
 * @Date 2025/4/14 16:45
 */
@AllArgsConstructor
public class BizLogFormatter implements StructuredHttpLogFormatter {
    private static final ZoneId UTC_8 = ZoneId.of("Asia/Shanghai");

    private final ObjectMapper mapper;

    @Override
    public String format(final Map<String, Object> content) throws IOException {
        return mapper.writeValueAsString(content);
    }

    @Override
    public Map<String, Object> prepare(final Precorrelation precorrelation, final HttpRequest request)
            throws IOException {
        final String correlationId = precorrelation.getId();

        MDC.put("traceId", correlationId);

        final Map<String, Object> content = new LinkedHashMap<>();

        content.put("time", precorrelation.getStart().atZone(UTC_8));
        content.put("type", "request");
        content.put("traceId", correlationId);
        content.put("protocol", request.getProtocolVersion());
        content.put("remote", request.getRemote());
        content.put("method", request.getMethod());
        content.put("uri", request.getRequestUri());
        content.put("host", request.getHost());
        content.put("path", request.getPath());
        content.put("scheme", request.getScheme());
        content.put("port", preparePort(request));

        prepareHeaders(request).ifPresent(headers -> content.put("headers", headers));
        prepareBody(request).ifPresent(body -> content.put("req", body));

        return content;
    }

    @Override
    public Map<String, Object> prepare(final Correlation correlation, final HttpResponse response) throws IOException {
        final Map<String, Object> content = new LinkedHashMap<>();

        content.put("time", correlation.getEnd().atZone(UTC_8));
        content.put("type", "response");
        content.put("traceId", correlation.getId());
        content.put("protocol", response.getProtocolVersion());
        content.put("status", response.getStatus());

        prepareHeaders(response).ifPresent(headers -> content.put("headers", headers));
        prepareBody(response).ifPresent(body -> content.put("rsp", body));

        return content;
    }
}
